package com.culturalCenter.dataCenter.schedule.site;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSON;
import com.culturalCenter.dataCenter.Utils.ClassUtil;
import com.culturalCenter.dataCenter.Utils.RedisUtil;
import com.culturalCenter.dataCenter.customEntity.site.pull.SiteBookingEntity;
import com.culturalCenter.dataCenter.customEntity.site.pull.SiteEntity;
import com.culturalCenter.dataCenter.customEntity.site.pull.SiteManageSiteEntity;
import com.culturalCenter.dataCenter.entity.Sites;
import com.culturalCenter.dataCenter.entity.site.*;
import com.culturalCenter.dataCenter.mapper.site.*;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.client.HttpServerErrorException;
import org.springframework.web.client.RestTemplate;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.util.*;

/**
 * 定时任务_场地_拉取
 *
 * @author 方治森
 * @since 2022/4/20
 */
@Component
@Slf4j
@Async("dataThreadExecutor")
public class SiteDataPull {

    private long site_timestamp1;
    private long site_timestamp2;
    private long site_timestamp3;
    private long site_timestamp4;
    @Value("${tuchuang.hostname}")
    private String hostname;
    @Value("${placeManage.hostname}")
    private String placeManageHost;
    @Resource
    private RestTemplate restTemplate;
    @Resource
    private SiteMapper siteMapper;
    @Resource
    private SiteBookingMapper siteBookingMapper;
    @Resource
    private SiteBookingMonthMapper siteBookingMonthMapper;
    @Resource
    private SiteAlertsMapper siteAlertsMapper;
    @Resource
    private SiteAlertsMonthMapper siteAlertsMonthMapper;
    @Resource
    private RedisUtil redisUtil;
    @Resource
    private RedissonClient redisson;
    private final long size = 500;

    /**
     * 初始化时间戳
     */
    @PostConstruct
    public void initTimestamp() {
        site_timestamp1 = !redisUtil.redisTemplate.hasKey("site_timestamp1") ? 0 : Long.parseLong(redisUtil.get("site_timestamp1"));
        site_timestamp2 = !redisUtil.redisTemplate.hasKey("site_timestamp2") ? 0 : Long.parseLong(redisUtil.get("site_timestamp2"));
        site_timestamp3 = !redisUtil.redisTemplate.hasKey("site_timestamp3") ? 0 : Long.parseLong(redisUtil.get("site_timestamp3"));

        // for test
        // site_timestamp1 = 0;
        // site_timestamp2 = 0;
        // site_timestamp3 = 0;
        // for (int i = 1; i <= 3; i++) {
        //     redisUtil.del("site_lock" + i);
        // }
    }

    /**
     * 获取返回数据中的data
     */
    public String getResponse(String uri, Map<String, Object> param) {
        try {
            String url = hostname + uri + "?" + ClassUtil.setParamString(param);
            String responseJson = restTemplate.getForObject(url, String.class);
            return JSON.parseObject(responseJson).getString("data");
        } catch (HttpServerErrorException e) {
            log.error("TCC综合管理平台服务端异常，请联系TCC相关人员");
            throw e;
        }
    }

    /**
     * 获取返回数据中的data(场地管理)
     */
    public String getSiteResponse(String uri, Map<String, Object> param) {
        String url = placeManageHost + uri + "?" + ClassUtil.setParamString(param);
        String responseJson = restTemplate.getForObject(url, String.class);
        return JSON.parseObject(responseJson).getString("data");
    }

    /**
     * 场地(cdc_site图创)
     */
//     @Scheduled(cron = "${cron.sitePull}")
//     @Scheduled(cron = "${cron.test}")
    public void pullSiteList() {
        log.info("'cdc_site(图创)'开始拉取。。。。。");
        Map<String, Object> param = new TreeMap<>();
        long current = 1;
        param.put("updateTimestamp", site_timestamp1);
        param.put("current", current);
        param.put("size", size);
        String data = getResponse("/api/tcc-mes-service/client-api/bigData/room/listBaseInfoPage", param);
        long total = Long.parseLong(JSON.parseObject(data).getString("total"));
        List<Site> siteList = new ArrayList<>();
        long pages = total % size == 0 ? total / size : total / size + 1;
        for (; current <= pages; current++) {
            param.put("current", current);
            insertSiteList(getResponse("/api/tcc-mes-service/client-api/bigData/room/listBaseInfoPage", param),
                    siteList);
            if (siteList.size()!=0){
            redisUtil.set("site_timestamp1",
                    Long.toString(siteList.stream().max(Comparator.comparing(Site::getUpdateTime)).get().getUpdateTime().getTime()));}
            siteList.clear();
        }  //todo 初始化项目需执行上面的代码 从图创拉取初始数据   后续数据执行下面代码拉取逻辑
        /* ObjectMapper objectMapper = new ObjectMapper();
         List<Sites> list = restTemplate.getForObject(placeManageHost+"/v1/app/site/getAllSite", List.class);
         List<Site> siteList = new ArrayList<>();
         if (CollectionUtils.isNotEmpty(list)){
             for (int i = 0; i < list.size(); i++) {
                 Sites sites = objectMapper.convertValue(list.get(i),Sites.class);
                 Site site = new Site();
                 BeanUtils.copyProperties(sites,site);
                 siteList.add(site);
             }
         }*/
//         log.info("场地返回的list：{}",siteList);
         siteMapper.insertBatch(siteList);
        log.info("'cdc_site(图创)'拉取完毕。。。。。");
    }

    private void insertSiteList(String data, List<Site> siteList) {
        List<SiteEntity> dataList = JSON.parseArray(JSON.parseObject(data).getString("records"),
                SiteEntity.class);
        if (CollectionUtils.isNotEmpty(dataList)) {
            for (SiteEntity dataElement : dataList) {
                if (!StringUtils.isEmpty(dataElement.getPlaceNo())) {
                    Site site = new Site();
                    site.setRefId(String.valueOf(dataElement.getId()));
                    site.setRuleId(dataElement.getRuleId());
                    site.setCode(dataElement.getPlaceNo());
                    site.setSiteName(dataElement.getName());
                    site.setLocation(dataElement.getAddress());
                    site.setGalleryful(Integer.valueOf(dataElement.getGalleryful()));
                    site.setSize(dataElement.getArea());
                    site.setContacts(dataElement.getPrincipalName());
                    site.setPhone(dataElement.getPrincipalPhone());
                    site.setOpenType(dataElement.getOpenType());
                    site.setSource(2);
                    site.setPicture(dataElement.getCoverImg());
                    site.setStatus((int) dataElement.getStatus());
                    site.setUpdateTime(dataElement.getUpdateTime());
                    siteList.add(site);
                }
            }
            if (CollectionUtils.isNotEmpty(siteList)) {
                siteMapper.insertBatch(siteList);
            }
        }
    }

    /**
     * 场地预约信息(该定时任务需在"场地规则列表任务"执行完后执行)(cdc_site_booking、cdc_site_booking_month)
     */
//    @Scheduled(cron = "${cron.sitePull}")
//     @Scheduled(cron = "${cron.test}")
    public void pullSiteBookingList() {
        String lockKey = "site_lock1";
        RLock redissonLock = redisson.getLock(lockKey);
        try {
            boolean locked = redissonLock.isLocked();
            if (!locked){
                redissonLock.lock();
            }
            log.info("'cdc_site_booking、cdc_site_booking_month'开始拉取。。。。。");

            Map<String, Object> param = new TreeMap<>();
            long current = 1;
            param.put("updateTimestamp", site_timestamp2);
            param.put("size", size);
            param.put("current", current);
            String data = getResponse("/api/tcc-mes-service/client-api/bigData/room/listApplyInfoPage", param);
            long pages = Long.parseLong(JSON.parseObject(data).getString("pages"));
            List<SiteBooking> siteBookingList = new ArrayList<>();
            for (; current <= pages; current++) {
                param.put("current", current);
                insertSiteBookingList(getResponse("/api/tcc-mes-service/client-api/bigData/room/listApplyInfoPage", param),
                        siteBookingList);
                log.info("接到的返回数据:--------------------",siteBookingList.toString());
                siteBookingMapper.insertBatch(siteBookingList);
                redisUtil.set("site_timestamp2",
                        Long.toString(siteBookingList.stream().max(Comparator.comparing(SiteBooking::getUpdateTime)).get().getUpdateTime().getTime()));
                siteBookingList.clear();
            }
            // 插入本月排期
            List<SiteBookingMonth> siteBookingMonthList = siteBookingMapper.selectSiteBookingMonth();
            if (CollectionUtils.isNotEmpty(siteBookingMonthList)) {
                siteBookingMonthMapper.deleteAll();
                siteBookingMonthMapper.insertBatch(siteBookingMonthList);
            }
            log.info("'cdc_site_booking、cdc_site_booking_month'拉取完毕。。。。。");
        } finally {
            boolean locked = redissonLock.isLocked();
            if (locked){
                redissonLock.unlock();
            }
        }
    }

    private void insertSiteBookingList(String data, List<SiteBooking> siteBookingList) {
        List<SiteBookingEntity> dataList = JSON.parseArray(JSON.parseObject(data).getString("records"),
                SiteBookingEntity.class);
        if (CollectionUtils.isNotEmpty(dataList)) {
            for (SiteBookingEntity dataElement : dataList) {
                SiteBooking siteBooking = new SiteBooking();
                siteBooking.setRefId(String.valueOf(dataElement.getId()));
                siteBooking.setSiteUser(dataElement.getApplyName());
                siteBooking.setApplyUnit(dataElement.getApplyUnit());
                siteBooking.setSiteId(String.valueOf(dataElement.getRoomId()));
                siteBooking.setSiteCode(String.valueOf(dataElement.getPlaceNo()));
                siteBooking.setPurpose(dataElement.getApplyCause());
                siteBooking.setPeopleNum(dataElement.getPeopleNum());
                siteBooking.setUserType(dataElement.getApplyType());
                siteBooking.setBeginTime(dataElement.getUseStartTime());
                siteBooking.setEndTime(dataElement.getUseEndTime());
                siteBooking.setMobile(dataElement.getUsername());
                siteBooking.setExamine(dataElement.getExamine());
                siteBooking.setRoomClassifyName(dataElement.getRoomClassifyName());
                siteBooking.setStatus(1);
                // if (dataElement.getSignInStatus() == 4) {
                // siteBooking.setStatus(2);
                // } else if (dataElement.getSignInStatus() == 1 || dataElement.getSignInStatus() == 2 ||
                // dataElement.getSignInStatus() == 3) {
                // siteBooking.setStatus(3);
                // }
                // if (dataElement.getSignOutStatus() == 1 || dataElement.getSignOutStatus() == 2) {
                // siteBooking.setStatus(4);
                // }
                // if (dataElement.getStatus() == 0) {
                // siteBooking.setStatus(-1);
                // }
                // if (dataElement.getDelTag() == 1) {
                // siteBooking.setStatus(-3);
                // }
                if (dataElement.getDelTag() == 1) {
                    siteBooking.setStatus(-3);
                } else {
                    if (dataElement.getStatus() == 0) {
                        siteBooking.setStatus(-1);
                    } else {
                        if (dataElement.getSignInStatus() == 4) {
                            siteBooking.setStatus(2);
                        } else if (dataElement.getSignInStatus() == 5
                                && dataElement.getUseStartTime().after(new Date())) {
                            siteBooking.setStatus(5);
                        } else if (dataElement.getUseEndTime().before(new Date())) {
                            siteBooking.setStatus(4);
                        } else if (dataElement.getUseStartTime().before(new Date())
                                && dataElement.getUseEndTime().after(new Date())) {
                            siteBooking.setStatus(3);
                        }
                    }
                }
                siteBooking.setRemark(dataElement.getRemark());
                siteBooking.setUpdateTime(dataElement.getUpdateTime());
                siteBookingList.add(siteBooking);
            }
        }
    }

    /**
     * 报警信息(cdc_site_alerts、cdc_site_alerts_month场地管理)
     */
//    @Scheduled(cron = "${cron.sitePull}")
    // @Scheduled(cron = "${cron.test}")
    public void pullSiteAlerts() {
        String lockKey = "site_lock2";
        RLock redissonLock = redisson.getLock(lockKey);
        try {
            boolean locked = redissonLock.isLocked();
            if (!locked){
                redissonLock.lock();
            }
            log.info("'cdc_site_alerts、cdc_site_alerts_month'开始拉取。。。。。");

            Map<String, Object> param = new HashMap<>();
            long current = 1;
            param.put("pageNum", current);
            param.put("pageSize", size);
            param.put("date", DateUtil.date(site_timestamp3));
            String data = getSiteResponse("/v1/app/camera/getAlertsInfo", param);
            JSONObject object = JSONUtil.parseObj(data);
            long pages = object.getLong("pages");
            List<SiteAlerts> siteAlertsList = new ArrayList<>();
            for (; current <= pages; current++) {
                param.put("current", current);
                siteAlertsList.addAll(JSON.parseArray(JSON.parseObject(getSiteResponse("/v1/app/camera/getAlertsInfo", param)).getString("list"), SiteAlerts.class));
                siteAlertsMapper.insertBatch(siteAlertsList);
                redisUtil.set("site_timestamp3", Long.toString(siteAlertsList.stream().max(Comparator.comparing(SiteAlerts::getAlertsTime)).get().getAlertsTime().getTime()));
                siteAlertsList.clear();
            }
            // 插入本月报警
            List<SiteAlertsMonth> siteAlertsMonthList = siteAlertsMapper.selectSiteAlertMonth();
            if (CollectionUtils.isNotEmpty(siteAlertsMonthList)) {
                siteAlertsMonthMapper.deleteAll();
                siteAlertsMonthMapper.insertBatch(siteAlertsMonthList);
            }

            log.info("'cdc_site_alerts、cdc_site_alerts_month'拉取完毕。。。。。");
        } finally {
            boolean locked = redissonLock.isLocked();
            if (locked){
                redissonLock.unlock();
            }
        }
    }

    /**
     * 场地(cdc_site场地管理)
     */
//    @Scheduled(cron = "${cron.sitePull}")
    // @Scheduled(cron = "${cron.test}")
    public void pullSite() {
        String lockKey = "site_lock3";
        RLock redissonLock = redisson.getLock(lockKey);
        try {
            boolean locked = redissonLock.isLocked();
            if (!locked){
                redissonLock.lock();
            }
            log.info("'cdc_site(场地管理)'开始拉取。。。。。");

            int pageNum = 1;
            Map<String, Object> param = new HashMap<>();
            param.put("pageNum", pageNum);
            param.put("pageSize", size);
            param.put("timestamp", site_timestamp4);
            String data = getSiteResponse("/v1/webApi/site/getSite", param);
            JSONObject object = JSONUtil.parseObj(data);
            long pages = object.getLong("pages");
            List<Site> siteList = new ArrayList<>();
            for (; pageNum <= pages; pageNum++) {
                param.put("pageNum", pageNum);
                insertSite(getSiteResponse("/v1/webApi/site/getSite", param), siteList);
                siteMapper.insertBatch(siteList);
            }
            // 时间戳
            /*
             * List<Date> updateTimeList = siteList.stream().filter(w -> w.getUpdateTime() !=
             * null).map(Site::getUpdateTime).collect(Collectors.toList()); if
             * (CollectionUtils.isNotEmpty(updateTimeList)) { Date timeLatest = Collections.max(updateTimeList);
             * site_timestamp4 = timeLatest.getTime(); //存redis redisUtil.set("site_timestamp4", Long.toString(site_timestamp4)); }
             */

            log.info("'cdc_site(场地管理)'拉取完毕。。。。。");
        } finally {
            boolean locked = redissonLock.isLocked();
            if (locked){
                redissonLock.unlock();
            }
        }
    }

    private void insertSite(String data, List<Site> siteList) {
        List<SiteManageSiteEntity> dataList = JSON.parseArray(JSON.parseObject(data).getString("data"),
                SiteManageSiteEntity.class);
        if (CollectionUtils.isNotEmpty(dataList)) {
            for (SiteManageSiteEntity dataElement : dataList) {
                if (!StringUtils.isEmpty(dataElement.getCode())) {
                    Site site = new Site();
                    site.setRefId(dataElement.getId());
                    site.setCode(dataElement.getCode());
                    site.setArea(dataElement.getAreaName());
                    if (StrUtil.isNotEmpty(dataElement.getCategoryName().trim())) {
                        site.setCategory(dataElement.getCategoryName());
                    }
                    site.setSiteName(dataElement.getSiteName());
                    site.setLocation(dataElement.getLocation());
                    site.setGalleryful(dataElement.getGalleryful());
                    if (dataElement.getSize() != null) {
                        site.setSize(Double.toString(dataElement.getSize()));
                    }
                    site.setContacts(dataElement.getContacts());
                    site.setPhone(dataElement.getPhone());
                    if (dataElement.getOpenStatus() != null) {
                        site.setOpenType(Integer.toString(dataElement.getOpenStatus()));
                    }
                    site.setPlan(dataElement.getPlan());
                    site.setSource(dataElement.getSource());
                    site.setPicture(dataElement.getPicture());
                    site.setStatus(dataElement.getStatus());
                    site.setUpdateTime(dataElement.getCreateTime());
                    siteList.add(site);
                }
            }
        }
    }

}
